package com.jielihaofeng.chat.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jielihaofeng.chat.constants.MessageTypeEnum;
import com.jielihaofeng.chat.convert.ChatMessageConvert;
import com.jielihaofeng.chat.dao.ChatMessageDao;
import com.jielihaofeng.chat.entity.ChatMessageEntity;
import com.jielihaofeng.chat.query.ChatMessageQuery;
import com.jielihaofeng.chat.service.ChatGroupUserService;
import com.jielihaofeng.chat.service.ChatMessageService;
import com.jielihaofeng.chat.vo.ChatMessageVO;
import com.jielihaofeng.framework.common.page.PageResult;
import com.jielihaofeng.framework.common.service.impl.BaseServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 消息表
 *
 * @author 阿沐 babamu@126.com
 * @since 1.0.0 2022-07-22
 */
@Service
@AllArgsConstructor
public class ChatMessageServiceImpl extends BaseServiceImpl<ChatMessageDao, ChatMessageEntity> implements ChatMessageService {

    private ChatGroupUserService chatGroupUserService;

    private ChatMessageDao chatMessageDao;

    @Override
    public PageResult<ChatMessageVO> page(ChatMessageQuery query) {
        IPage<ChatMessageEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));

        return new PageResult<>(ChatMessageConvert.INSTANCE.convertList(page.getRecords()), page.getTotal());
    }

    private LambdaQueryWrapper<ChatMessageEntity> getWrapper(ChatMessageQuery query) {
        LambdaQueryWrapper<ChatMessageEntity> lambdaQueryWrapper = new LambdaQueryWrapper<ChatMessageEntity>().eq(ChatMessageEntity::getType, query.getMessageType()).eq(ChatMessageEntity::getSender, query.getSender()).eq(ChatMessageEntity::getReceiver, query.getReceiver()).orderByDesc(ChatMessageEntity::getCreateTime);
        return lambdaQueryWrapper;
    }

    @Override
    public void save(ChatMessageVO vo) {
        ChatMessageEntity entity = ChatMessageConvert.INSTANCE.convert(vo);

        baseMapper.insert(entity);
    }

    @Override
    public void update(ChatMessageVO vo) {
        ChatMessageEntity entity = ChatMessageConvert.INSTANCE.convert(vo);

        updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> idList) {
        removeByIds(idList);
    }


    /**
     * 发送消息
     *
     * @param vo 消息vo
     */
    @Override
    public ChatMessageEntity sendMessage(ChatMessageVO vo) {
        ChatMessageEntity entity = ChatMessageConvert.INSTANCE.convert(vo);
        baseMapper.insert(entity);
        return entity;
    }

    /**
     * 获取所有消息列表
     *
     * @param userId 用户id
     * @return 消息列表
     */
    @Override
    public List<ChatMessageEntity> getAllMessageList(Long userId) {
        // 查单聊信息
        LambdaQueryWrapper<ChatMessageEntity> queryWrapper = new LambdaQueryWrapper<ChatMessageEntity>()
                .eq(ChatMessageEntity::getType, MessageTypeEnum.SINGLE.getCode())
                .in(ChatMessageEntity::getReceiver, userId).or().in(ChatMessageEntity::getSender, userId);
        // 查群组信息
        List<Long> groupIdList = chatGroupUserService.getGroupIdList(userId);
        if (CollectionUtil.isNotEmpty(groupIdList)) {
            queryWrapper.or(wrapper -> wrapper.eq(ChatMessageEntity::getType, MessageTypeEnum.GROUP.getCode())
                    .in(ChatMessageEntity::getReceiver, groupIdList));
        }
        // 查询消息
        return baseMapper.selectList(queryWrapper);
    }


    /**
     * 获取消息列表
     *
     * @param query 查询参数
     * @return 消息列表
     */
    @Override
    public PageResult<ChatMessageEntity> getMessageList(ChatMessageQuery query) {
        String messageType = query.getMessageType();
        MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(messageType);
        if (messageTypeEnum == null) {
            throw new RuntimeException("获取消息列表失败：没有匹配到消息类型");
        }
        LambdaQueryWrapper<ChatMessageEntity> chatMessageEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (messageTypeEnum == MessageTypeEnum.SINGLE) {
            // 如果是单聊，交换发送人和接收人加入到查询条件
            chatMessageEntityLambdaQueryWrapper = new LambdaQueryWrapper<ChatMessageEntity>()
                    // 如果传了消息id，说明要查这个id之前的数据，所以要过滤掉这个id后的数据，即查询的消息id要小于这个id
                    .lt(ObjectUtils.isNotEmpty(query.getMessageId()), ChatMessageEntity::getId, query.getMessageId())
                    .eq(ChatMessageEntity::getType, query.getMessageType())
                    .eq(ChatMessageEntity::getSender, query.getSender())
                    .eq(ChatMessageEntity::getReceiver, query.getReceiver());
            chatMessageEntityLambdaQueryWrapper.or(
                    wrapper -> wrapper
                            .lt(ObjectUtils.isNotEmpty(query.getMessageId()), ChatMessageEntity::getId, query.getMessageId())
                            .eq(ChatMessageEntity::getType, query.getMessageType())
                            .eq(ChatMessageEntity::getSender, query.getReceiver()).eq(ChatMessageEntity::getReceiver, query.getSender()));
        } else if (messageTypeEnum == MessageTypeEnum.GROUP) {
            // 如果是群聊
            chatMessageEntityLambdaQueryWrapper = new LambdaQueryWrapper<ChatMessageEntity>()
                    .lt(ObjectUtils.isNotEmpty(query.getMessageId()), ChatMessageEntity::getId, query.getMessageId())
                    .eq(ChatMessageEntity::getType, query.getMessageType())
                    .eq(ChatMessageEntity::getReceiver, query.getReceiver());
        }
        chatMessageEntityLambdaQueryWrapper.orderByDesc(ChatMessageEntity::getCreateTime).orderByDesc(ChatMessageEntity::getId);
        IPage<ChatMessageEntity> page = baseMapper.selectPage(getPage(query), chatMessageEntityLambdaQueryWrapper);
        return new PageResult<>(page.getRecords(), page.getTotal());
    }


}
